import 'package:flutter/material.dart';
import 'package:waterfall_flow/waterfall_flow.dart';

import 'footer_widget.dart';

/// Copyright (C), 2021-2023, Franky Lee
/// @ProjectName: vmcard
/// @Package:
/// @ClassName: load_state
/// @Description:
/// @Author: frankylee
/// @CreateDate: 2023/5/23 11:45
/// @UpdateUser: frankylee
/// @UpdateData: 2023/5/23 11:45
/// @UpdateRemark: 更新说明
enum LoadState { idle, loading, noMore, fail }

class CustomListView<T> extends StatefulWidget {
  const CustomListView({
    super.key,
    this.onRefresh,
    this.onLoadMore,
    this.data,
    this.renderItem,
    this.separator,
    this.footerState = LoadState.idle,
    this.sliverHeader,
    this.header,
    this.footer,
    this.empty,
    this.physics,
    this.controller,
    this.sliverGridDelegate,
    this.sliverWaterfallFlowDelegate,
    this.padding,
    this.attachController = true,
    this.isNest = false,
    this.reverse = false,
    this.scrollDirection = Axis.vertical,
    this.isMessage = false,
  });

  final Future<void> Function()? onRefresh;
  final Future<void> Function()? onLoadMore;

  final List<T>? data;

  final Widget Function(BuildContext context, int index, dynamic item)?
  renderItem;

  final Widget Function(BuildContext context, int index)? separator;

  final LoadState? footerState;

  final Widget? header;
  final Widget? footer;

  final List<Widget>? sliverHeader;

  final Widget? empty;

  final ScrollPhysics? physics;

  final ScrollController? controller;

  final SliverGridDelegate? sliverGridDelegate;

  final SliverWaterfallFlowDelegate? sliverWaterfallFlowDelegate;

  final EdgeInsetsGeometry? padding;

  final bool attachController;

  final bool isNest;

  final bool reverse;

  final Axis scrollDirection;

  final bool isMessage;

  @override
  CustomListViewState createState() => CustomListViewState();
}

class CustomListViewState extends State<CustomListView> {
  late ScrollController _scrollController;

  bool _loadMore = false;

  Future _refresh() async {
    _loadMore = true;
    await widget.onRefresh?.call();
    _loadMore = false;
  }

  void _load() async {
    if (widget.footerState == LoadState.noMore ||
        widget.footerState == LoadState.loading ||
        widget.footerState == null) {
      return;
    }
    _loadMore = true;
    await widget.onLoadMore?.call();
    _loadMore = false;
  }

  @override
  void initState() {
    _scrollController = widget.controller ?? ScrollController();
    _scrollController.addListener(() {
      if (!widget.isNest) {
        if (_scrollController.position.extentAfter < 300 && !_loadMore) {
          _load();
        }
      }
    });
    super.initState();
  }

  /// custom scrollview
  Widget _buildScrollView() {
    Widget child;
    Widget footer;
    if (widget.data != null && widget.data!.isNotEmpty) {
      if (widget.sliverWaterfallFlowDelegate != null) {
        child = SliverWaterfallFlow(
          delegate: SliverChildBuilderDelegate(
            childCount: widget.data?.length ?? 0,
            (BuildContext c, int index) {
              return widget.renderItem?.call(
                context,
                index,
                widget.data?[index],
              );
            },
          ),
          gridDelegate: widget.sliverWaterfallFlowDelegate!,
        );
      } else if (widget.sliverGridDelegate != null) {
        /// grid
        child = SliverGrid(
          delegate: SliverChildBuilderDelegate((
            BuildContext context,
            int index,
          ) {
            return widget.renderItem?.call(context, index, widget.data?[index]);
          }, childCount: widget.data?.length ?? 0),
          gridDelegate: widget.sliverGridDelegate!,
        );
      } else {
        /// list
        child = SliverList.separated(
          itemCount: widget.data?.length ?? 0,
          itemBuilder: (BuildContext context, int index) {
            return widget.renderItem?.call(context, index, widget.data?[index]);
          },
          separatorBuilder: (BuildContext context, int index) {
            if (widget.separator != null) {
              return widget.separator!(context, index);
            }
            return Container();
          },
        );
      }

      footer = FooterWidget(
        state: widget.footerState ?? LoadState.idle,
        isMessage: widget.isMessage,
      );
    } else {
      child = SliverToBoxAdapter(child: widget.empty ?? Container());
      footer = Container();
    }
    return NotificationListener(
      onNotification: (ScrollNotification scrollInfo) {
        if (widget.isNest) {
          if (!_loadMore && scrollInfo.metrics.extentAfter < 300) {
            _load();
          }
        }
        return false;
      },
      child: CustomScrollView(
        scrollDirection: widget.scrollDirection,
        reverse: widget.reverse,
        physics: widget.physics ?? const AlwaysScrollableScrollPhysics(),
        controller: widget.attachController ? _scrollController : null,
        slivers: [
          ...?widget.sliverHeader,
          SliverToBoxAdapter(child: widget.header),
          SliverPadding(
            padding: widget.padding ?? EdgeInsets.zero,
            sliver: child,
          ),
          SliverToBoxAdapter(child: widget.footer),
          SliverToBoxAdapter(child: footer),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    if (widget.onRefresh != null) {
      return RefreshIndicator(
        color: const Color(0xFFFF3F4E),
        onRefresh: _refresh,
        child: _buildScrollView(),
      );
    }
    return _buildScrollView();
  }
}
